#include "BlockQueue.hpp"
#include "Thread.hpp"
#include <vector>
#include <unistd.h>
#include <string>
#include <ctime>
#include "Task.hpp"
using namespace ThreadModule;
// int number = 15;
int cnt = 66;
using BlockQueue_t = BlockQueue<Task>;

void calu()
{
    srand(time(nullptr) ^ pthread_self());
    sleep(1);
    int a = rand() % 1357;
    int b = rand() % 1357;
    usleep(1234);
    std::cout<<a<<"+"<<b<<"="<<a+b<<std::endl;
}

void Consumer(BlockQueue_t &bq)
{
    while (true)
    {
        Task t;
        bq.Pop(t);
        t();
        // t.Excute();
        // std::cout << t.Result() << std::endl;
    }
}

void Productor(BlockQueue_t &bq)
{

    while (true)
    {
        // Task t(a, b);
        // bq.Enqueue(t);
        bq.Enqueue(calu);
    }
}

void StartComm(std::vector<Thread<BlockQueue_t>> *tds, int num, BlockQueue_t &bq, func_t<BlockQueue_t> func)
{
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread - " + std::to_string(i + 1);
        tds->emplace_back(func, bq, name);
        tds->back().Start();
    }
}

void StartConsumer(std::vector<Thread<BlockQueue_t>> *tds, int num, BlockQueue_t &bq)
{
    StartComm(tds, num, bq, Consumer);
}

void StartProductor(std::vector<Thread<BlockQueue_t>> *tds, int num, BlockQueue_t &bq)
{
    StartComm(tds, num, bq, Productor);
}

void WaitAllThread(std::vector<Thread<BlockQueue_t>> tds)
{
    for (auto &td : tds)
    {
        td.Join();
    }
}

int main()
{
    BlockQueue_t *bq = new BlockQueue_t(5);
    std::vector<Thread<BlockQueue_t>> threads;
    StartConsumer(&threads, 3, *bq);
    StartProductor(&threads, 4, *bq);
    WaitAllThread(threads);
    return 0;
}